package com.atguigu.gmall.common.config.threadpool;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author A
 * @version 1.0
 * @description: TODO
 * @date 2024/9/14 23:32
 */
@EnableConfigurationProperties(AppTreadPoolProperties.class)
@Configuration
public class AppTreadPoolAutoConfig {

    //    int corePoolSize,
//    int maximumPoolSize,
//    long keepAliveTime,
//    TimeUnit unit,
//    BlockingQueue<Runnable> workQueue,
//    ThreadFactory
//    RejectedExecutionHandler handler
//    @Autowired
//    private AppTreadPoolProperties poolProperties;
    @Primary
    @Bean
    public ThreadPoolExecutor corePool(AppTreadPoolProperties poolProperties, @Value("${spring.application.name:default}") String threadName) {
        ThreadPoolExecutor corePool = new ThreadPoolExecutor(poolProperties.getCorePoolSize(), poolProperties.getMaximumPoolSize(), poolProperties.getKeepAliveTime(), poolProperties.getUnit(),
                new LinkedBlockingDeque<>(poolProperties.getQueueSize()),
                new AppThreadFactory(threadName + "-core"),
                poolProperties.getRejectedHander()
        );

        return corePool;
    }

    @Bean
    public ThreadPoolExecutor otherPool(AppTreadPoolProperties poolProperties, @Value("${spring.application.name:default}") String threadName) {
        ThreadPoolExecutor otherPool = new ThreadPoolExecutor(poolProperties.getCorePoolSize() / 2, poolProperties.getMaximumPoolSize() / 2, poolProperties.getKeepAliveTime(), poolProperties.getUnit(),
                new LinkedBlockingDeque<>(poolProperties.getQueueSize() / 2),
                new AppThreadFactory(threadName + "-other"),
                poolProperties.getRejectedHander()
        );

        return otherPool;
    }

    @Bean
    public ScheduledExecutorService schedulePool(@Value("${spring.application.name:default}") String threadName) {
        ScheduledExecutorService schedulePool = Executors.newScheduledThreadPool(10, new AppThreadFactory(threadName + "-schedule"));


        return schedulePool;
    }

    class AppThreadFactory implements ThreadFactory {
        private String threadName = null;
        AtomicInteger count = new AtomicInteger(1);

        public AppThreadFactory(String threadName) {
            this.threadName = threadName;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setName("[" + threadName + "]" + count.getAndIncrement());
            return thread;
        }
    }
}
